//###############
//FILE : InitializationRequest.java
//WRITER : Daniel Lowengrub, daniel_i_l, 320687098
//EXERCISE : oop ex3 2011
//DESCRIPTION:
//See below
//###############

package oop.ex3.nameserver;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.util.ArrayList;

import oop.ex3.communication.SocketAddress;
import oop.ex3.protocol.sessions.NameInitSession;

/**
 * This implements the FM requests that start in the way specified in the assignment.
 * It first handles the Begin session and then tries to continue with one of the request handlers in it's
 * list. If it doesn't find any then it's also in charge of ending the session.
 * @author daniel
 */
public class InitializationRequest extends NameServerRequest{
    private NameInitSession _initSession;

    private ArrayList<FileManagerSpecificRequest> _specificRequests;

    /**
     * Create a new request. It's gets a nameserver db which it passes to the super class.
     * @param nameDb The name database to use.
     */
    public InitializationRequest(NameServerDatabase nameDb) {
        super(nameDb, new NameInitSession());
        _initSession = (NameInitSession)_openingSession;
        _specificRequests = new ArrayList<FileManagerSpecificRequest>();
    }

    /**
     * Add a request to the list of FM specific requests. These are the request that the
     * handler will try to run afer finishing the initial session.
     * @param request
     */
    public void addRequest(FileManagerSpecificRequest request) {
        _specificRequests.add(request);
    }

    @Override
    public boolean serveRequest(DataInputStream inputStream, DataOutputStream outputStream) {
        //first run the init session
        //System.out.println("serving init request");
        ArrayList<String> fileNames = new ArrayList<String>();
        ArrayList<SocketAddress>  nameServers = new ArrayList<SocketAddress>();
        ArrayList<SocketAddress> fileServers = _nameServerDb.getFileManagers();

        _initSession.setFileNames(fileNames);
        _initSession.setNameServers(nameServers);
        _initSession.setRecognizedFileServers(fileServers);

        if (!_initSession.executeSession(inputStream, outputStream)) {
            return false;
        }

      //if everything went ok then check if we have to update the database
        if (_initSession.newFileServer()) {
            FileManagerInfo info = new FileManagerInfo(fileNames);
            _nameServerDb.addFileManager(_initSession.getFileAddress(), info);
            _nameServerDb.addNameServerList(nameServers);

            //System.out.println("added file server with " + fileNames.size() + "files");
        }

        //now look for another request
        //System.out.println("looking for specific requests");
        boolean endedSession = false; //a flag checking if we've ended the session
        
        for (FileManagerSpecificRequest request : _specificRequests) {
            if (request.matchHeader(inputStream)) {
                request.setFileManager(_initSession.getFileAddress());
                if (!request.serveRequest(inputStream, outputStream)) //if the session wans't successful
                	return false;
                else {//the session was successfull
                	endedSession = true;
                	break;
                }
            }
        }
        
        //System.out.println("we didn't find one");
        //if we haven't ended yet then try to end the session
        if (!endedSession){
        	//if we couldn't end the session then there was an error
        	if (!_endSession.executeSession(inputStream, outputStream))
        		return false;
        }
        
      
        
        return true;

    }

    @Override
    public NameServerRequest getCopy() {
        InitializationRequest copy = new InitializationRequest(_nameServerDb);
        for (FileManagerSpecificRequest request : _specificRequests)
            copy.addRequest((FileManagerSpecificRequest) request.getCopy());

        return copy;
    }

}
